#include "StdAfx.h"
#include "UserEnumerator.h"

using namespace Adaptive::Foundation;
using namespace Adaptive::Win32;

/*--------------------------------------------------------------------------------
 * Constructor / Dispose / Destructor Methods
 *------------------------------------------------------------------------------*/
#pragma region Constructor / Dispose / Destructor Methods
// Initializes a new instance of the class.
UserEnumerator::UserEnumerator()
{
}
#pragma endregion

/*--------------------------------------------------------------------------------
 * Public Methods / Functions
 *------------------------------------------------------------------------------*/
#pragma region Public Methods / Functions
/// Gets the list of account names as defined on the local machine.
StringCollection^ UserEnumerator::LoadUserAccountNames()
{
    USER_INFO_0* data = NULL;					//Structure to return account name.
    int result = 0;                             //Result of API call.
    DWORD totalEntries = 0;                     //Total count of users on the machine.
    DWORD entriesRead = 0;                      //Number of actual entries read.
    DWORD preferredMaxLength = 65536;           //Max length parameter.
    int count = 0;                              //Iteration counter.

    BYTE* bufferPtr = NULL;						//Original pointer to memory space returned by API call.
    DWORD resumeHandle = NULL;					//Result handle for API call.
	IntPtr localPtr = IntPtr::Zero;             //Local pointer for reading data from memory space.
    StringCollection^ returnValue = nullptr;    //Return value.
	CString machineName = System::Environment::MachineName;
    returnValue = gcnew StringCollection();

    //Make the call.
    try
    {
		result = ::NetUserEnum(machineName, 0, FILTER_NORMAL_ACCOUNT, &bufferPtr, preferredMaxLength,
								&entriesRead, &totalEntries, &resumeHandle);
			
    }
    catch (...)
    {
		result = -1;
    }

    //If successful, read each structure from the memory space.
    if ((result == 0) || (result == 234))
    {
		//Convert the pointer to a structure.
        data = (USER_INFO_0*)bufferPtr;
        do
        {
			returnValue->Add(gcnew String( data[count].usri0_name ));
            //Advance the pointer.
            count++;
        } while (count < (int)entriesRead);

        //Close handle.
		::NetApiBufferFree(bufferPtr);
    }

    return returnValue;
}
/// <summary>
/// Gets the list of user paths for all accounts on the system.
/// </summary>
/// <returns>
/// A <see cref="UserPathInfo"/> array containing the list of paths for 
/// each user.
/// </returns>
array<UserPathInfo^>^ UserEnumerator::EnumerateUserKeys()
{
    RegistryKey^			shellKey = nullptr;         //Key for explorer - shell folders key.
    RegistryKey^			userKey = nullptr;          //HKEY_USERS\* key pointer.
    UserPathInfo^			newInfo = nullptr;          //User path information instance.
    array<UserPathInfo^>^	returnValue = nullptr;      //Return value.
    SecurityIdentifier^		secureId = nullptr;			//Registry-specified SID for account.
    NTAccount^				ntAccount = nullptr;        //Windows NT Account information.
    array<String^>^			nameList = nullptr;         //List of key names.
    int						length = 0;                 //Iteration length.
    int						count = 0;                  //Iteration counter.
    List<UserPathInfo^>^	list = nullptr;             //Temporary container list.

    list = gcnew List<UserPathInfo^>();
	nameList = Registry::Users->GetSubKeyNames();
    length = nameList->Length;
    for (count = 0; count < length; count++)
    {
        try
        {
            secureId = gcnew SecurityIdentifier(nameList[count]);
			ntAccount = (NTAccount^)secureId->Translate(NTAccount::typeid);
        }
        catch (...)
        {
            secureId = nullptr;
            ntAccount = nullptr;
        }

        if (secureId != nullptr)
        {
			userKey = Registry::Users->OpenSubKey(nameList[count]);
            if (userKey != nullptr)
            {
                shellKey = userKey->OpenSubKey(PATH_KEY);
                if (shellKey != nullptr)
                {
                    newInfo = gcnew UserPathInfo(ntAccount->Value);

                    newInfo->Cache = (String^)shellKey->GetValue(PATH_CACHE);
                    newInfo->Cookies = (String^)shellKey->GetValue(PATH_COOKIES);
                    newInfo->History = (String^)shellKey->GetValue(PATH_HISTORY);
                    newInfo->LocalSettings = (String^)shellKey->GetValue(PATH_LOCALSETTINGS);
                    newInfo->Recent = (String^)shellKey->GetValue(PATH_RECENT);

                    list->Add(newInfo);
                    shellKey->Close();
                    delete(shellKey);
                }
                userKey->Close();
                delete(userKey);
            }
        }
        secureId = nullptr;
        ntAccount = nullptr;

    }

    returnValue = list->ToArray();
    list->Clear();
    delete(list);

    return returnValue;

}
#pragma endregion
